﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows;
using System.Linq;
using System.Windows.Controls.Primitives;
using System.Windows.Data;

namespace Gmantis.Controls.DataGrid
{
    public class DataGridRowCollection : IEnumerable<DataGridRow>, IEnumerable, INotifyCollectionChanged
    {
        // Fields
        private AggregatingTable<int, IntSumAggregator> _groupCountDataSourceItemTable;
        private AggregatingTable<int, IntSumAggregator> _groupCountTable;
        internal List<DataGridGroupRow> _groups;
        private ObservableCollection<DataGridRow> bottomRows;
        private VirtualList items;
        private ObservableCollection<DataGridRow> topRows;

        // Events
        internal event EventHandler<DataGridRowEventArgs> AfterRowLoaded;
        internal event EventHandler<DataGridRowEventArgs> BeforeRowUnloaded;
        internal event EventHandler<NotifyCollectionChangedEventArgs> BottomRowsChanged;
        public event NotifyCollectionChangedEventHandler CollectionChanged;
        internal event EventHandler<NotifyCollectionChangedEventArgs> TopRowsChanged;

        // Methods
        internal DataGridRowCollection(DataGridModel model, DataGridGroupRow ownerGroup)
        {
            Func<int, DataGridRow> func = null;
            Action<DataGridRow> action = null;
            NotifyCollectionChangedEventHandler handler = null;
            NotifyCollectionChangedEventHandler handler2 = null;
            this.items = new VirtualList(0);
            this._groups = new List<DataGridGroupRow>();
            this.topRows = new ObservableCollection<DataGridRow>();
            this.bottomRows = new ObservableCollection<DataGridRow>();
            this.Model = model;
            this.OwnerGroup = ownerGroup;
            this.Source = new ReadOnlyObservableCollection<object>(new System.Collections.ObjectModel.ObservableCollection<object>());
            if (func == null)
            {
                func = index => this.Model.CreateRow(DataGridRowType.Item, this.GetDataItem(index));
            }
            this.items.ItemRequested += func;
            if (action == null)
            {
                action = row => this.LoadRow(row, DataGridRowType.Item);
            }
            this.items.ItemLoaded += action;
            this.items.CountChanged += new Action(this.InvalidateCount);
            if (handler == null)
            {
                handler = delegate(object s, NotifyCollectionChangedEventArgs e)
                {
                    switch (e.Action)
                    {
                        case NotifyCollectionChangedAction.Add:
                            foreach (DataGridRow row in e.NewItems)
                            {
                                this.LoadRow(row, DataGridRowType.Top);
                            }
                            break;

                        case NotifyCollectionChangedAction.Remove:
                        case NotifyCollectionChangedAction.Reset:
                            if (e.OldItems != null)
                            {
                                foreach (DataGridRow row2 in e.OldItems)
                                {
                                    this.UnloadRow(row2);
                                }
                            }
                            break;

                        case NotifyCollectionChangedAction.Replace:
                            throw new Exception("Replace operation not supported in top and bottom rows.");
                    }
                    this.InvalidateCount();
                    if (!this.GetIsLoading())
                    {
                        this.OnTopRowsChanged(e);
                    }
                };
            }
            this.topRows.CollectionChanged += handler;
            if (handler2 == null)
            {
                handler2 = delegate(object s, NotifyCollectionChangedEventArgs e)
                {
                    switch (e.Action)
                    {
                        case NotifyCollectionChangedAction.Add:
                            foreach (DataGridRow row in e.NewItems)
                            {
                                this.LoadRow(row, DataGridRowType.Bottom);
                            }
                            break;

                        case NotifyCollectionChangedAction.Remove:
                        case NotifyCollectionChangedAction.Reset:
                            if (e.OldItems != null)
                            {
                                foreach (DataGridRow row2 in e.OldItems)
                                {
                                    this.UnloadRow(row2);
                                }
                            }
                            break;

                        case NotifyCollectionChangedAction.Replace:
                            throw new Exception("Replace operation not supported in top and bottom rows.");
                    }
                    this.InvalidateCount();
                    if (!this.GetIsLoading())
                    {
                        this.OnBottomRowsChanged(e);
                    }
                };
            }
            this.bottomRows.CollectionChanged += handler2;
        }

        public IEnumerable<DataGridRow> AsEnumerable(Predicate<DataGridRow> predicate, Predicate<DataGridGroupRow> recursionPredicate)
        {
            return this.AsEnumerable(predicate, recursionPredicate, true);
        }

        internal IEnumerable<DataGridRow> AsEnumerable(Predicate<DataGridRow> predicate, Predicate<DataGridGroupRow> recursionPredicate, bool forceLoadRows)
        {
            foreach (DataGridRow iteratorVariable0 in this.TopRows)
            {
                if ((predicate == null) || predicate(iteratorVariable0))
                {
                    yield return iteratorVariable0;
                }
            }
            foreach (DataGridGroupRow iteratorVariable1 in this._groups)
            {
                if ((this.Model.DataGrid.GroupRowPosition == DataGridGroupRowPosition.AboveData) && ((predicate == null) || predicate(iteratorVariable1)))
                {
                    yield return iteratorVariable1;
                }
                if ((recursionPredicate == null) || recursionPredicate(iteratorVariable1))
                {
                    foreach (DataGridRow iteratorVariable2 in iteratorVariable1.Rows.AsEnumerable(predicate, recursionPredicate))
                    {
                        yield return iteratorVariable2;
                    }
                }
                if ((this.Model.DataGrid.GroupRowPosition == DataGridGroupRowPosition.BelowData) && ((predicate == null) || predicate(iteratorVariable1)))
                {
                    yield return iteratorVariable1;
                }
            }
            foreach (DataGridRow iteratorVariable3 in forceLoadRows ? this.GetItems(this.items) : this.items.GetLoadedItems())
            {
                if ((iteratorVariable3 == null) || ((predicate != null) && !predicate(iteratorVariable3)))
                {
                    continue;
                }
                yield return iteratorVariable3;
            }
            foreach (DataGridRow iteratorVariable4 in this.BottomRows)
            {
                if ((predicate != null) && !predicate(iteratorVariable4))
                {
                    continue;
                }
                yield return iteratorVariable4;
            }
        }

        internal void Clear(bool preserveTopAndBottomRows)
        {
            this.UnloadRows(preserveTopAndBottomRows);
            foreach (DataGridGroupRow row in this._groups)
            {
                row.Rows.Clear(false);
            }
            this._groups.Clear();
            if (!preserveTopAndBottomRows)
            {
                if (this.TopRows.Count > 0)
                {
                    this.TopRows.Clear();
                }
                if (this.BottomRows.Count > 0)
                {
                    this.BottomRows.Clear();
                }
            }
            this.items.Clear();
            this._groupCountTable = null;
            this._groupCountDataSourceItemTable = null;
            this.OnCollectionChanged(false);
        }

        public void Collapse(Predicate<DataGridGroupRow> predicate)
        {
            foreach (DataGridGroupRow row in this._groups)
            {
                if ((predicate == null) || predicate(row))
                {
                    row.GroupRowsVisibility = Visibility.Collapsed;
                }
                if (row.Rows._groups.Count > 0)
                {
                    row.Rows.Collapse(predicate);
                }
            }
            if (this.OwnerGroup == null)
            {
                this.Model.OnRowsCollapsed(new EventArgs());
            }
        }

        public void CollapseAll()
        {
            this.Collapse(null);
        }

        public bool Contains(int index)
        {
            return ((0 <= index) && (index < this.GetCount()));
        }

        internal int DataSourceOffset(DataGridRow row)
        {
            int num;
            if ((this.OwnerGroup == null) || (this.OwnerGroup.ParentCollection == null))
            {
                num = 0;
            }
            else
            {
                num = this.OwnerGroup.ParentCollection.DataSourceOffset(this.OwnerGroup);
            }
            if (row.Type == DataGridRowType.Item)
            {
                return ((num + this.GroupCountDataSourceItemTable.TotalLength()) + row.LocalIndex);
            }
            if (row.Type == DataGridRowType.Group)
            {
                return (num + this.GroupCountDataSourceItemTable.FindByIndex(row.LocalIndex).Offset);
            }
            return -1;
        }

        public void Expand(Predicate<DataGridGroupRow> predicate)
        {
            foreach (DataGridGroupRow row in this._groups)
            {
                if ((predicate == null) || predicate(row))
                {
                    row.GroupRowsVisibility = Visibility.Visible;
                }
                if (row.Rows._groups.Count > 0)
                {
                    row.Rows.Expand(predicate);
                }
            }
            if (this.OwnerGroup == null)
            {
                this.Model.OnRowsExpanded(new EventArgs());
            }
        }

        public void ExpandAll()
        {
            this.Expand(null);
        }

        internal int GetCount()
        {
            return (((this.TopRows.Count + this.BottomRows.Count) + this.GroupCountTable.TotalLength()) + this.items.Count);
        }

        private int GetCountDataSourceItem()
        {
            return (this.GroupCountDataSourceItemTable.TotalLength() + this.items.Count);
        }

        internal object GetDataItem(int dataSourceIndex)
        {
            if (this.Source != null)
            {
                return this.Source[this.GroupCountDataSourceItemTable.Count + dataSourceIndex];
            }
            return this.Model.DataConnection.GetDataItem(dataSourceIndex);
        }

        public IEnumerator<DataGridRow> GetEnumerator()
        {
            return new DataGridRowCollectionEnumerator(this);
        }

        public DataGridRow GetFirstVisibleRow(bool includeCollapsedGroupRows = false)
        {
            return this.GetVisibleRowsFromTop(includeCollapsedGroupRows).FirstOrDefault<DataGridRow>();
        }

        private bool GetIsLoading()
        {
            if ((this.OwnerGroup != null) && (this.OwnerGroup.ParentCollection != null))
            {
                return this.OwnerGroup.ParentCollection.GetIsLoading();
            }
            return this.IsLoading;
        }

        private IEnumerable<DataGridRow> GetItems(VirtualList vl)
        {
            int iteratorVariable0 = 0;
            while (true)
            {
                if (iteratorVariable0 >= vl.Count)
                {
                    yield break;
                }
                yield return vl[iteratorVariable0];
                iteratorVariable0++;
            }
        }

        public DataGridRow GetLastVisibleRow(bool includeCollapsedGroupRows = false)
        {
            return this.GetVisibleRowsFromBottom(includeCollapsedGroupRows).FirstOrDefault<DataGridRow>();
        }

        public IEnumerable<DataGridRow> GetLoadedRows()
        {
            List<DataGridRow> result = new List<DataGridRow>();
            this.GetLoadedRows(result);
            return result;
        }

        private void GetLoadedRows(List<DataGridRow> result)
        {
            result.AddRange(this.TopRows);
            foreach (DataGridGroupRow row in this._groups)
            {
                result.Add(row);
                row.Rows.GetLoadedRows(result);
            }
            result.AddRange(this.items.GetLoadedItems());
            result.AddRange(this.BottomRows);
        }

        internal DataGridRow GetRow(int index)
        {
            if ((index < 0) || (index >= this.GetCount()))
            {
                throw new IndexOutOfRangeException();
            }
            int num = 0;
            if ((index - num) < this.topRows.Count)
            {
                return this.topRows[index - num];
            }
            num += this.topRows.Count;
            if ((index - num) < this.GroupCountTable.TotalLength())
            {
                IndexOffset<int> offset = this.GroupCountTable.FindByLength(index - num);
                DataGridGroupRow row = this._groups[offset.Index];
                if (this.Model.DataGrid.GroupRowPosition == DataGridGroupRowPosition.AboveData)
                {
                    if ((index - num) == offset.Offset)
                    {
                        return row;
                    }
                    return row.Rows.GetRow(((index - num) - offset.Offset) - 1);
                }
                if (this.Model.DataGrid.GroupRowPosition == DataGridGroupRowPosition.BelowData)
                {
                    if ((index - num) == (offset.Offset + row.Rows.Count))
                    {
                        return row;
                    }
                    return row.Rows.GetRow((index - num) - offset.Offset);
                }
            }
            num += this.GroupCountTable.TotalLength();
            if ((index - num) < this.items.Count)
            {
                return this.items[index - num];
            }
            num += this.items.Count;
            if ((index - num) < this.bottomRows.Count)
            {
                return this.bottomRows[index - num];
            }
            return null;
        }

        internal DataGridRow GetRowFromDataItem(object dataItem)
        {
            int index = this.Model.DataConnection.IndexOf(dataItem);
            if (index >= 0)
            {
                return this.GetRowFromDataSourceIndex(index);
            }
            return null;
        }

        internal DataGridRow GetRowFromDataSourceIndex(int dataSourceIndex)
        {
            if (dataSourceIndex >= 0)
            {
                if (dataSourceIndex < this.GroupCountDataSourceItemTable.TotalLength())
                {
                    IndexOffset<int> offset = this.GroupCountDataSourceItemTable.FindByLength(dataSourceIndex);
                    DataGridGroupRow row = this._groups[offset.Index];
                    return row.Rows.GetRowFromDataSourceIndex(dataSourceIndex - offset.Offset);
                }
                dataSourceIndex -= this.GroupCountDataSourceItemTable.TotalLength();
                if (dataSourceIndex < this.items.Count)
                {
                    return this.items[dataSourceIndex];
                }
            }
            return null;
        }

        public IEnumerable<DataGridRow> GetVisibleRowsFromBottom(bool includeCollapsedGroupRows = false)
        {
            return this.GetVisibleRowsFromIndex(this.Count - 1, GeneratorDirection.Backward, includeCollapsedGroupRows);
        }

        public IEnumerable<DataGridRow> GetVisibleRowsFromIndex(int fromRowIndex, GeneratorDirection direction, bool includeCollapsedGroupRows = false)
        {
            int count = this.Count;
            if (((count != 0) && ((fromRowIndex >= 0) || (direction != GeneratorDirection.Backward))) && ((fromRowIndex <= (count - 1)) || (direction != GeneratorDirection.Forward)))
            {
                int iteratorVariable1 = Math.Max(0, Math.Min(count - 1, fromRowIndex));
                do
                {
                    DataGridRow iteratorVariable2 = this[iteratorVariable1];
                    if (iteratorVariable2.IsVisible(includeCollapsedGroupRows))
                    {
                        yield return iteratorVariable2;
                    }
                    iteratorVariable1 += (direction == GeneratorDirection.Forward) ? 1 : -1;
                }
                while ((iteratorVariable1 >= 0) && (iteratorVariable1 < count));
            }
        }

        public IEnumerable<DataGridRow> GetVisibleRowsFromTop(bool includeCollapsedGroupRows = false)
        {
            return this.GetVisibleRowsFromIndex(0, GeneratorDirection.Forward, includeCollapsedGroupRows);
        }

        private void group_GroupRowsVisibilityChanged(object sender, PropertyChangedEventArgs<Visibility> e)
        {
            DataGridGroupRow group = sender as DataGridGroupRow;
            this.Model.OnGroupRowVisibilityChanged(group);
        }

        internal int IndexOf(DataGridRow row)
        {
            int num;
            if (this.OwnerGroup == null)
            {
                num = 0;
            }
            else if (this.Model.DataGrid.GroupRowPosition == DataGridGroupRowPosition.AboveData)
            {
                num = 1 + this.OwnerGroup.Index;
            }
            else
            {
                num = this.OwnerGroup.Index - this.OwnerGroup.Rows.Count;
            }
            if (row.LocalIndex == -1)
            {
                int index = this.TopRows.IndexOf(row);
                if (index != -1)
                {
                    return (num + index);
                }
                int num3 = this.BottomRows.IndexOf(row);
                if (num3 != -1)
                {
                    return ((((num + this.TopRows.Count) + this.GroupCountTable.TotalLength()) + this.items.Count) + num3);
                }
            }
            else
            {
                if (row.Type == DataGridRowType.Item)
                {
                    return (((num + this.TopRows.Count) + this.GroupCountTable.TotalLength()) + row.LocalIndex);
                }
                if (row.Type == DataGridRowType.Group)
                {
                    if (this.Model.DataGrid.GroupRowPosition == DataGridGroupRowPosition.AboveData)
                    {
                        return ((num + this.TopRows.Count) + this.GroupCountTable.FindByIndex(row.LocalIndex).Offset);
                    }
                    return ((((num + this.TopRows.Count) + this.GroupCountTable.FindByIndex(row.LocalIndex + 1).Offset) + this.BottomRows.Count) - 1);
                }
            }
            return -1;
        }

        public int IndexOf(object dataItem)
        {
            DataGridRow row = this[dataItem];
            if (row == null)
            {
                return -1;
            }
            return row.Index;
        }

        internal void InsertGroup(int index, DataGridGroupRow group)
        {
            group.LocalIndex = index;
            this._groups.Insert(index, group);
            for (int i = index + 1; i < this._groups.Count; i++)
            {
                this._groups[i].LocalIndex = i;
            }
            group.GroupRowsVisibilityChanged += new EventHandler<PropertyChangedEventArgs<Visibility>>(this.group_GroupRowsVisibilityChanged);
            group.Rows.AfterRowLoaded += (s, e) => this.RaiseAfterRowLoaded(e);
            group.Rows.BeforeRowUnloaded += (s, e) => this.RaiseBeforeRowUnloaded(e);
            group.Rows.TopRowsChanged += (s, e) => this.OnTopRowsChanged(e);
            group.Rows.BottomRowsChanged += (s, e) => this.OnBottomRowsChanged(e);
            this.InvalidateCount();
            this.LoadRow(group, DataGridRowType.Group);
        }

        internal DataGridRow InsertRow(int addedLocalIndex, object addedItem)
        {
            DataGridRow newItem = this.Model.CreateRow(DataGridRowType.Item, addedItem);
            newItem.ParentCollection = this;
            newItem.Type = DataGridRowType.Item;
            this.items.Insert(addedLocalIndex, newItem);
            this.RaiseAfterRowLoaded(new DataGridRowEventArgs(newItem));
            this.OnCollectionChanged(true);
            return newItem;
        }

        internal void InvalidateCount()
        {
            this._groupCountTable = null;
            this._groupCountDataSourceItemTable = null;
            if ((this.OwnerGroup != null) && (this.OwnerGroup.ParentCollection != null))
            {
                this.OwnerGroup.ParentCollection.InvalidateCount();
            }
        }

        internal void Load(bool preserveTopAndBottomRows, GroupedField[] groupedFields, ReadOnlyObservableCollection<object> groups)
        {
            this.IsLoading = true;
            this.Clear(preserveTopAndBottomRows);
            if (groupedFields.Count<GroupedField>() > 0)
            {
                this.LoadGroupInDepth(new object[0], (from gc in groupedFields select gc.PropertyName).ToArray<string>(), groups);
            }
            else
            {
                this.LoadItems(this.Model.DataConnection.Count);
            }
            this.IsLoading = false;
            this.OnCollectionChanged(true);
        }

        private void LoadGroupInDepth(object[] groupKeys, string[] groupedFields, ReadOnlyObservableCollection<object> groups)
        {
            this.Source = groups;
            string groupPropertyPath = groupedFields[groupKeys.Length];
            DataGridColumn column = this.Model.Columns.FirstOrDefault<DataGridColumn>(col => col.ActualSortMemberPath == groupPropertyPath);
            if (groups != null)
            {
                foreach (CollectionViewGroup group in groups)
                {
                    DataGridGroupRow row = this.Model.CreateGroup(groupKeys, column, group);
                    this.InsertGroup(this._groups.Count, row);
                    if (group.IsBottomLevel)
                    {
                        row.Rows.LoadItems(group.Items);
                    }
                    else
                    {
                        row.Rows.LoadGroupInDepth(row.GroupKeys, groupedFields, group.Items);
                    }
                }
            }
        }

        private void LoadItems(int itemsCount)
        {
            this.Source = null;
            this.items.Count = itemsCount;
        }

        private void LoadItems(ReadOnlyObservableCollection<object> source)
        {
            this.Source = source;
            this.items.Count = source.Count;
        }

        private void LoadRow(DataGridRow row, DataGridRowType type)
        {
            if (row.ParentCollection != null)
            {
                throw new Exception("This row is already added to other row collection.");
            }
            row.ParentCollection = this;
            if (row.Type == DataGridRowType.Undefined)
            {
                row.Type = type;
            }
            this.RaiseAfterRowLoaded(new DataGridRowEventArgs(row));
        }

        private void OnBottomRowsChanged(NotifyCollectionChangedEventArgs e)
        {
            EventHandler<NotifyCollectionChangedEventArgs> bottomRowsChanged = this.BottomRowsChanged;
            if (bottomRowsChanged != null)
            {
                bottomRowsChanged(this, e);
            }
            this.OnCollectionChanged(true);
        }

        private void OnCollectionChanged(bool bubbleChange = true)
        {
            this.InvalidateCount();
            if ((bubbleChange && (this.OwnerGroup != null)) && (this.OwnerGroup.ParentCollection != null))
            {
                this.OwnerGroup.ParentCollection.OnCollectionChanged(true);
            }
            if (this.CollectionChanged != null)
            {
                this.CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
            }
        }

        private void OnTopRowsChanged(NotifyCollectionChangedEventArgs e)
        {
            EventHandler<NotifyCollectionChangedEventArgs> topRowsChanged = this.TopRowsChanged;
            if (topRowsChanged != null)
            {
                topRowsChanged(this, e);
            }
            this.OnCollectionChanged(true);
        }

        private void RaiseAfterRowLoaded(DataGridRowEventArgs e)
        {
            EventHandler<DataGridRowEventArgs> afterRowLoaded = this.AfterRowLoaded;
            if (afterRowLoaded != null)
            {
                afterRowLoaded(this, e);
            }
        }

        private void RaiseBeforeRowUnloaded(DataGridRowEventArgs e)
        {
            EventHandler<DataGridRowEventArgs> beforeRowUnloaded = this.BeforeRowUnloaded;
            if (beforeRowUnloaded != null)
            {
                beforeRowUnloaded(this, e);
            }
        }

        internal void RemoveGroup(DataGridGroupRow group)
        {
            group.Rows.Clear(false);
            this.UnloadRow(group);
            for (int i = group.LocalIndex + 1; i < this._groups.Count; i++)
            {
                this._groups[i - 1] = this._groups[i];
                this._groups[i - 1].LocalIndex = i - 1;
            }
            this._groups.RemoveAt(this._groups.Count - 1);
            this.InvalidateCount();
        }

        internal void RemoveRows(DataGridRow[] removedRows)
        {
            foreach (DataGridRow row in removedRows)
            {
                this.UnloadRow(row);
                this.items.Remove(row);
            }
            this.OnCollectionChanged(true);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new DataGridRowCollectionEnumerator(this);
        }

        private void UnloadRow(DataGridRow row)
        {
            this.RaiseBeforeRowUnloaded(new DataGridRowEventArgs(row));
            row.ParentCollection = null;
        }

        private void UnloadRows(bool preserveTopAndBottomRows)
        {
            foreach (DataGridGroupRow row in this._groups)
            {
                row.Rows.UnloadRows(false);
                this.UnloadRow(row);
            }
            if (!preserveTopAndBottomRows)
            {
                foreach (DataGridRow row2 in this.TopRows)
                {
                    this.UnloadRow(row2);
                }
                foreach (DataGridRow row3 in this.BottomRows)
                {
                    this.UnloadRow(row3);
                }
            }
            foreach (DataGridRow row4 in this.items._items.Values)
            {
                this.UnloadRow(row4);
            }
        }

        // Properties
        public Collection<DataGridRow> BottomRows
        {
            get
            {
                return this.bottomRows;
            }
        }

        public int Count
        {
            get
            {
                return this.GetCount();
            }
        }

        internal AggregatingTable<int, IntSumAggregator> GroupCountDataSourceItemTable
        {
            get
            {
                if (this._groupCountDataSourceItemTable == null)
                {
                    this._groupCountDataSourceItemTable = new AggregatingTable<int, IntSumAggregator>(from g in this._groups select g.Rows.GetCountDataSourceItem());
                }
                return this._groupCountDataSourceItemTable;
            }
        }

        internal AggregatingTable<int, IntSumAggregator> GroupCountTable
        {
            get
            {
                if (this._groupCountTable == null)
                {
                    this._groupCountTable = new AggregatingTable<int, IntSumAggregator>(from g in this._groups select 1 + g.Rows.GetCount());
                }
                return this._groupCountTable;
            }
        }

        public bool IsLoading { get; set; }

        internal bool IsVisible
        {
            get
            {
                return (((this.OwnerGroup == null) || (this.OwnerGroup.ParentCollection == null)) || ((this.OwnerGroup.GroupRowsVisibility == Visibility.Visible) && this.OwnerGroup.ParentCollection.IsVisible));
            }
        }

        public DataGridRow this[object item]
        {
            get
            {
                if (item != null)
                {
                    DataGridRow rowFromDataItem = this.GetRowFromDataItem(item);
                    if (rowFromDataItem != null)
                    {
                        return rowFromDataItem;
                    }
                    foreach (DataGridRow row2 in this.TopRows)
                    {
                        if (item.Equals(row2.DataItem))
                        {
                            return row2;
                        }
                    }
                    foreach (DataGridRow row3 in this.BottomRows)
                    {
                        if (item.Equals(row3.DataItem))
                        {
                            return row3;
                        }
                    }
                    foreach (DataGridGroupRow row4 in this._groups)
                    {
                        if (item.Equals(row4.DataItem))
                        {
                            return row4;
                        }
                        rowFromDataItem = row4.Rows[item];
                        if (rowFromDataItem != null)
                        {
                            return rowFromDataItem;
                        }
                    }
                }
                return null;
            }
        }

        public DataGridRow this[int index]
        {
            get
            {
                return this.GetRow(index);
            }
        }

        internal DataGridModel Model { get; private set; }

        public DataGridGroupRow OwnerGroup { get; private set; }

        internal ReadOnlyObservableCollection<object> Source { get; set; }

        public Collection<DataGridRow> TopRows
        {
            get
            {
                return this.topRows;
            }
        }
    }
}
